home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 2 / Meeting Pearls Vol. II (1995)(GTI - Schatztruhe)[!].iso / Pearls / gfx / pbm / source / jpegV5.lha / jpegV5 / src / rdrle.c < prev    next >
C/C++ Source or Header  |  1994-12-23  |  11KB  |  385 lines

  1. /*
  2.  * rdrle.c
  3.  *
  4.  * Copyright (C) 1991-1994, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains routines to read input images in Utah RLE format.
  9.  * The Utah Raster Toolkit library is required (version 3.1 or later).
  10.  *
  11.  * These routines may need modification for non-Unix environments or
  12.  * specialized applications.  As they stand, they assume input from
  13.  * an ordinary stdio stream.  They further assume that reading begins
  14.  * at the start of the file; start_input may need work if the
  15.  * user interface has already read some data (e.g., to determine that
  16.  * the file is indeed RLE format).
  17.  *
  18.  * Based on code contributed by Mike Lijewski,
  19.  * with updates from Robert Hutchinson.
  20.  */
  21.  
  22. #include "cdjpeg.h"        /* Common decls for cjpeg/djpeg applications */
  23.  
  24. #ifdef RLE_SUPPORTED
  25.  
  26. /* rle.h is provided by the Utah Raster Toolkit. */
  27.  
  28. #include <rle.h>
  29.  
  30. /*
  31.  * We assume that JSAMPLE has the same representation as rle_pixel,
  32.  * to wit, "unsigned char".  Hence we can't cope with 12- or 16-bit samples.
  33.  */
  34.  
  35. #if BITS_IN_JSAMPLE != 8
  36.   Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
  37. #endif
  38.  
  39. /*
  40.  * We support the following types of RLE files:
  41.  *   
  42.  *   GRAYSCALE   - 8 bits, no colormap
  43.  *   MAPPEDGRAY  - 8 bits, 1 channel colomap
  44.  *   PSEUDOCOLOR - 8 bits, 3 channel colormap
  45.  *   TRUECOLOR   - 24 bits, 3 channel colormap
  46.  *   DIRECTCOLOR - 24 bits, no colormap
  47.  *
  48.  * For now, we ignore any alpha channel in the image.
  49.  */
  50.  
  51. typedef enum
  52.   { GRAYSCALE, MAPPEDGRAY, PSEUDOCOLOR, TRUECOLOR, DIRECTCOLOR } rle_kind;
  53.  
  54.  
  55. /*
  56.  * Since RLE stores scanlines bottom-to-top, we have to invert the image
  57.  * to conform to JPEG's top-to-bottom order.  To do this, we read the
  58.  * incoming image into a virtual array on the first get_pixel_rows call,
  59.  * then fetch the required row from the virtual array on subsequent calls.
  60.  */
  61.  
  62. typedef struct _rle_source_struct * rle_source_ptr;
  63.  
  64. typedef struct _rle_source_struct {
  65.   struct cjpeg_source_struct pub; /* public fields */
  66.  
  67.   rle_kind visual;              /* actual type of input file */
  68.   jvirt_sarray_ptr image;       /* virtual array to hold the image */
  69.   rle_hdr header;               /* Input file information */
  70.   rle_pixel** rle_row;          /* holds a row returned by rle_getrow() */
  71.  
  72. } rle_source_struct;
  73.  
  74.  
  75. /*
  76.  * Read the file header; return image size and component count.
  77.  */
  78.  
  79. METHODDEF void
  80. start_input_rle (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  81. {
  82.   rle_source_ptr source = (rle_source_ptr) sinfo;
  83.   JDIMENSION width, height;
  84. #ifdef PROGRESS_REPORT
  85.   cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
  86. #endif
  87.  
  88.   /* Use RLE library routine to get the header info */
  89.   source->header = *rle_hdr_init(NULL);
  90.   source->header.rle_file = source->pub.input_file;
  91.   switch (rle_get_setup(&(source->header))) {
  92.   case RLE_SUCCESS:
  93.     /* A-OK */
  94.     break;
  95.   case RLE_NOT_RLE:
  96.     ERREXIT(cinfo, JERR_RLE_NOT);
  97.     break;
  98.   case RLE_NO_SPACE:
  99.     ERREXIT(cinfo, JERR_RLE_MEM);
  100.     break;
  101.   case RLE_EMPTY:
  102.     ERREXIT(cinfo, JERR_RLE_EMPTY);
  103.     break;
  104.   case RLE_EOF:
  105.     ERREXIT(cinfo, JERR_RLE_EOF);
  106.     break;
  107.   default:
  108.     ERREXIT(cinfo, JERR_RLE_BADERROR);
  109.     break;
  110.   }
  111.  
  112.   /* Figure out what we have, set private vars and return values accordingly */
  113.   
  114.   width  = source->header.xmax - source->header.xmin + 1;
  115.   height = source->header.ymax - source->header.ymin + 1;
  116.   source->header.xmin = 0;        /* realign horizontally */
  117.   source->header.xmax = width-1;
  118.  
  119.   cinfo->image_width      = width;
  120.   cinfo->image_height     = height;
  121.   cinfo->data_precision   = 8;  /* we can only handle 8 bit data */
  122.  
  123.   if (source->header.ncolors == 1 && source->header.ncmap == 0) {
  124.     source->visual     = GRAYSCALE;
  125.     TRACEMS2(cinfo, 1, JTRC_RLE_GRAY, width, height);
  126.   } else if (source->header.ncolors == 1 && source->header.ncmap == 1) {
  127.     source->visual     = MAPPEDGRAY;
  128.     TRACEMS3(cinfo, 1, JTRC_RLE_MAPGRAY, width, height,
  129.              1 << source->header.cmaplen);
  130.   } else if (source->header.ncolors == 1 && source->header.ncmap == 3) {
  131.     source->visual     = PSEUDOCOLOR;
  132.     TRACEMS3(cinfo, 1, JTRC_RLE_MAPPED, width, height,
  133.          1 << source->header.cmaplen);
  134.   } else if (source->header.ncolors == 3 && source->header.ncmap == 3) {
  135.     source->visual     = TRUECOLOR;
  136.     TRACEMS3(cinfo, 1, JTRC_RLE_FULLMAP, width, height,
  137.          1 << source->header.cmaplen);
  138.   } else if (source->header.ncolors == 3 && source->header.ncmap == 0) {
  139.     source->visual     = DIRECTCOLOR;
  140.     TRACEMS2(cinfo, 1, JTRC_RLE, width, height);
  141.   } else
  142.     ERREXIT(cinfo, JERR_RLE_UNSUPPORTED);
  143.   
  144.   if (source->visual == GRAYSCALE || source->visual == MAPPEDGRAY) {
  145.     cinfo->in_color_space   = JCS_GRAYSCALE;
  146.     cinfo->input_components = 1;
  147.   } else {
  148.     cinfo->in_color_space   = JCS_RGB;
  149.     cinfo->input_components = 3;
  150.   }
  151.  
  152.   /*
  153.    * A place to hold each scanline while it's converted.
  154.    * (GRAYSCALE scanlines don't need converting)
  155.    */
  156.   if (source->visual != GRAYSCALE) {
  157.     source->rle_row = (rle_pixel**) (*cinfo->mem->alloc_sarray)
  158.       ((j_common_ptr) cinfo, JPOOL_IMAGE,
  159.        (JDIMENSION) width, (JDIMENSION) cinfo->input_components);
  160.   }
  161.  
  162.   /* request a virtual array to hold the image */
  163.   source->image = (*cinfo->mem->request_virt_sarray)
  164.     ((j_common_ptr) cinfo, JPOOL_IMAGE,
  165.      (JDIMENSION) (width * source->header.ncolors),
  166.      (JDIMENSION) height, (JDIMENSION) 1);
  167.  
  168. #ifdef PROGRESS_REPORT
  169.   if (progress != NULL) {
  170.     /* count file input as separate pass */
  171.     progress->total_extra_passes++;
  172.   }
  173. #endif
  174.  
  175.   source->pub.buffer_height = 1;
  176. }
  177.  
  178.  
  179. /*
  180.  * Read one row of pixels.
  181.  * Called only after load_image has read the image into the virtual array.
  182.  * Used for GRAYSCALE, MAPPEDGRAY, TRUECOLOR, and DIRECTCOLOR images.
  183.  */
  184.  
  185. METHODDEF JDIMENSION
  186. get_rle_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  187. {
  188.   rle_source_ptr source = (rle_source_ptr) sinfo;
  189.  
  190.   source->pub.buffer = (*cinfo->mem->access_virt_sarray)
  191.     ((j_common_ptr) cinfo, source->image, cinfo->next_scanline, FALSE);
  192.  
  193.   return 1;
  194. }
  195.  
  196. /*
  197.  * Read one row of pixels.
  198.  * Called only after load_image has read the image into the virtual array.
  199.  * Used for PSEUDOCOLOR images.
  200.  */
  201.  
  202. METHODDEF JDIMENSION
  203. get_pseudocolor_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  204. {
  205.   rle_source_ptr source = (rle_source_ptr) sinfo;
  206.   JSAMPROW src_row, dest_row;
  207.   JDIMENSION col;
  208.   rle_map *colormap;
  209.   int val;
  210.  
  211.   colormap = source->header.cmap;
  212.   dest_row = source->pub.buffer[0];
  213.   src_row = * (*cinfo->mem->access_virt_sarray)
  214.     ((j_common_ptr) cinfo, source->image, cinfo->next_scanline, FALSE);
  215.  
  216.   for (col = cinfo->image_width; col > 0; col--) {
  217.     val = GETJSAMPLE(*src_row++);
  218.     *dest_row++ = colormap[val      ] >> 8;
  219.     *dest_row++ = colormap[val + 256] >> 8;
  220.     *dest_row++ = colormap[val + 512] >> 8;
  221.   }
  222.  
  223.   return 1;
  224. }
  225.  
  226.  
  227. /*
  228.  * Load the image into a virtual array.  We have to do this because RLE
  229.  * files start at the lower left while the JPEG standard has them starting
  230.  * in the upper left.  This is called the first time we want to get a row
  231.  * of input.  What we do is load the RLE data into the array and then call
  232.  * the appropriate routine to read one row from the array.  Before returning,
  233.  * we set source->pub.get_pixel_rows so that subsequent calls go straight to
  234.  * the appropriate row-reading routine.
  235.  */
  236.  
  237. METHODDEF JDIMENSION
  238. load_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  239. {
  240.   rle_source_ptr source = (rle_source_ptr) sinfo;
  241.   JDIMENSION row, col;
  242.   JSAMPROW  scanline, red_ptr, green_ptr, blue_ptr;
  243.   rle_pixel **rle_row;
  244.   rle_map *colormap;
  245.   char channel;
  246. #ifdef PROGRESS_REPORT
  247.   cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
  248. #endif
  249.  
  250.   colormap = source->header.cmap;
  251.   rle_row = source->rle_row;
  252.   row = cinfo->image_height;
  253.  
  254.   /* Read the RLE data into our virtual array.
  255.    * We assume here that (a) rle_pixel is represented the same as JSAMPLE,
  256.    * and (b) we are not on a machine where FAR pointers differ from regular.
  257.    */
  258.   RLE_CLR_BIT(source->header, RLE_ALPHA); /* don't read the alpha channel */
  259.  
  260. #ifdef PROGRESS_REPORT
  261.   if (progress != NULL) {
  262.     progress->pub.pass_limit = cinfo->image_height;
  263.     progress->pub.pass_counter = 0;
  264.     (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
  265.   }
  266. #endif
  267.  
  268.   switch (source->visual) {
  269.  
  270.   case GRAYSCALE:
  271.   case PSEUDOCOLOR:
  272.     while (row--) {
  273.       rle_row = (rle_pixel **) (*cinfo->mem->access_virt_sarray)
  274.          ((j_common_ptr) cinfo, source->image, row, TRUE);
  275.       rle_getrow(&source->header, rle_row);
  276. #ifdef PROGRESS_REPORT
  277.       if (progress != NULL) {
  278.         progress->pub.pass_counter++;
  279.         (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
  280.       }
  281. #endif
  282.     }
  283.     break;
  284.  
  285.   case MAPPEDGRAY:
  286.   case TRUECOLOR:
  287.     while (row--) {
  288.       scanline = * (*cinfo->mem->access_virt_sarray)
  289.         ((j_common_ptr) cinfo, source->image, row, TRUE);
  290.       rle_row = source->rle_row;
  291.       rle_getrow(&source->header, rle_row);
  292.  
  293.       for (col = 0; col < cinfo->image_width; col++) {
  294.         for (channel = 0; channel < source->header.ncolors; channel++) {
  295.           *scanline++ = (JSAMPLE)
  296.             colormap[GETJSAMPLE(rle_row[channel][col]) + 256 * channel] >> 8;
  297.         }
  298.       }
  299.  
  300. #ifdef PROGRESS_REPORT
  301.       if (progress != NULL) {
  302.         progress->pub.pass_counter++;
  303.         (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
  304.       }
  305. #endif
  306.     }
  307.     break;
  308.  
  309.   case DIRECTCOLOR:
  310.     while (row--) {
  311.       scanline = * (*cinfo->mem->access_virt_sarray)
  312.         ((j_common_ptr) cinfo, source->image, row, TRUE);
  313.       rle_getrow(&source->header, rle_row);
  314.  
  315.       red_ptr   = rle_row[0];
  316.       green_ptr = rle_row[1];
  317.       blue_ptr  = rle_row[2];
  318.  
  319.       for (col = cinfo->image_width; col > 0; col--) {
  320.         *scanline++ = *red_ptr++;
  321.         *scanline++ = *green_ptr++;
  322.         *scanline++ = *blue_ptr++;
  323.       }
  324.  
  325. #ifdef PROGRESS_REPORT
  326.       if (progress != NULL) {
  327.         progress->pub.pass_counter++;
  328.         (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
  329.       }
  330. #endif
  331.     }
  332.   }
  333.  
  334. #ifdef PROGRESS_REPORT
  335.   if (progress != NULL)
  336.     progress->completed_extra_passes++;
  337. #endif
  338.  
  339.   /* Set up to call proper row-extraction routine in future */
  340.   if (source->visual == PSEUDOCOLOR) {
  341.     source->pub.buffer = source->rle_row;
  342.     source->pub.get_pixel_rows = get_pseudocolor_row;
  343.   } else {
  344.     source->pub.get_pixel_rows = get_rle_row;
  345.   }
  346.  
  347.   /* And fetch the topmost (bottommost) row */
  348.   return (*source->pub.get_pixel_rows) (cinfo, sinfo);   
  349. }
  350.  
  351.  
  352. /*
  353.  * Finish up at the end of the file.
  354.  */
  355.  
  356. METHODDEF void
  357. finish_input_rle (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  358. {
  359.   /* no work */
  360. }
  361.  
  362.  
  363. /*
  364.  * The module selection routine for RLE format input.
  365.  */
  366.  
  367. GLOBAL cjpeg_source_ptr
  368. jinit_read_rle (j_compress_ptr cinfo)
  369. {
  370.   rle_source_ptr source;
  371.  
  372.   /* Create module interface object */
  373.   source = (rle_source_ptr)
  374.       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  375.                                   SIZEOF(rle_source_struct));
  376.   /* Fill in method ptrs */
  377.   source->pub.start_input = start_input_rle;
  378.   source->pub.finish_input = finish_input_rle;
  379.   source->pub.get_pixel_rows = load_image;
  380.  
  381.   return (cjpeg_source_ptr) source;
  382. }
  383.  
  384. #endif /* RLE_SUPPORTED */
  385.